/**
 * 
 */
package ${basepackage}.manager.impl.op;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import com.excalibur.shiro.shiro.util.ShiroUtils;
import com.excalibur.core.util.date.DateUtils;
import com.excalibur.core.util.EncryptUtils;
import com.excalibur.core.util.SpringUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import ${basepackage}.constant.SystemConstant;
import ${basepackage}.manager.op.OpUserManager;
import ${basepackage}.manager.exception.ServiceException;
import ${basepackage}.mapper.op.AuthorityMapper;
import ${basepackage}.mapper.op.OpUserMapper;
import ${basepackage}.mapper.op.RoleMapper;
import ${basepackage}.model.criteria.op.OpUserCriteria;
import ${basepackage}.model.po.op.Authority;
import ${basepackage}.model.po.op.OpUser;
import ${basepackage}.model.po.op.Role;
import ${basepackage}.model.po.op.UserRole;
import ${basepackage}.model.vo.common.Page;
import ${basepackage}.model.vo.op.opuser.AddOpUserForm;
import ${basepackage}.model.vo.op.opuser.OpUserRow;
import ${basepackage}.model.vo.op.opuser.UpdateAccountForm;
import ${basepackage}.model.vo.op.opuser.UpdateOpUserForm;
import ${basepackage}.model.vo.op.opuser.UpdatePasswordForm;

import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import com.github.miemiedev.mybatis.paginator.domain.PageList;

/**
 * @author "Jiance Qin"
 * 
 * @date 2014年2月24日
 * 
 * @time 下午5:32:06
 * 
 */
@Service
public class OpUserManagerImpl implements OpUserManager {

	protected static final String DEFAULT_NEW_PASSWORD = "onekeyop";

	@Value(value = "${r"#{configProperties['user.password.credentials.salt']}"}")
	private String defaultCredentialsSalt = "onekeyopcredentialssalt";

	@Autowired
	private OpUserMapper opUserMapper;
	@Autowired
	private RoleMapper roleMapper;
	@Autowired
	private AuthorityMapper authorityMapper;

	/**
	 * 
	 */
	public OpUserManagerImpl() {

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.general.op.manager.OpUserManager#delete(java.lang.Long)
	 */
	@Override
	public boolean delete(Long id) throws ServiceException {
		if (id == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.delete.IdNotNull"));
		}
		// 检查用户是否存在
		if (opUserMapper.get(id) == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.delete.NotExist"));
		}
		opUserMapper.remove(id);
		// 删除角色信息
		roleMapper.deleteUserRoleByUserId(id);
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.general.op.manager.OpUserManager#getOpUsers(com.general.op.model.
	 * criteria.OpUserCriteria, int, int)
	 */
	@Override
	public Page<OpUserRow> getOpUsers(OpUserCriteria criteria, int offset,
			int limit) throws ServiceException {
		if (criteria == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.getOpUsers.CriteriaNotNull"));
		}
		if (offset < 0) {
			offset = 0;
		}
		if (limit < 1) {
			limit = 1;
		}

		Page<OpUserRow> opUserRowList = new Page<OpUserRow>();
		PageList<OpUser> opUserList = opUserMapper.getList(criteria, new PageBounds(offset,
				limit, true));
		opUserRowList.setTotal(Long.valueOf(opUserList.getPaginator().getTotalCount()));

		List<OpUser> resultUserList = new ArrayList<OpUser>(opUserList);
		if (opUserList != null) {
			List<Role> roleList = null;
			for (OpUser opUser : opUserList) {
				roleList = roleMapper.getByUserId(opUser.getId());
				if (roleList != null) {
					opUser.setRoles(new LinkedHashSet<Role>(roleList));
					// 检查当前用户是否为超级管理员，如果不是，则去掉具有超级管理员中心各种权限的用户
					List<Authority> authoList = null;
					for (Role role : roleList) {
						authoList = authorityMapper.getByRoleId(role.getId());
						if (authoList != null) {
							for (Authority autho : authoList) {
								if (autho.getName().startsWith(
										SystemConstant.SUPER_ADMIN_AUTHO)) {
									if (!ShiroUtils
											.isPermitted(SystemConstant.SUPER_ADMIN_AUTHO)) {
										resultUserList.remove(opUser);
									}
								}
							}
						}
					}
				}
			}
		}
		List<OpUserRow> rowList = createOpUserRowList(resultUserList);
		opUserRowList.setRows(rowList);

		return opUserRowList;
	}

	/**
	 * 创建前台显示用户信息对象列表.
	 * 
	 * @param list
	 * @return
	 */
	protected List<OpUserRow> createOpUserRowList(List<OpUser> list) {
		if (list == null || list.isEmpty()) {
			return null;
		}
		List<OpUserRow> rowList = new ArrayList<OpUserRow>();
		OpUserRow row;
		for (OpUser opUser : list) {
			row = createOpUserRow(opUser);
			if (row != null) {
				rowList.add(row);
			}
		}
		return rowList;
	}

	/**
	 * 创建前台显示用户信息对象.
	 * 
	 * @param opUser
	 * @return
	 */
	protected OpUserRow createOpUserRow(OpUser opUser) {
		if (opUser == null) {
			return null;
		}
		OpUserRow row = new OpUserRow();
		row.setId(opUser.getId());
		row.setUsername(opUser.getUsername());
		row.setRealName(opUser.getRealName());
		row.setEmail(opUser.getEmail());
		row.setTel(opUser.getTel());
		row.setAccountDisabled(opUser.getAccountDisabled().booleanValue() ? SpringUtils
				.getI18nMessage("webapp.constant.yes") : SpringUtils
				.getI18nMessage("webapp.constant.no"));
		row.setAccountExpired(opUser.getAccountExpired().booleanValue() ? SpringUtils
				.getI18nMessage("webapp.constant.yes") : SpringUtils
				.getI18nMessage("webapp.constant.no"));
		row.setAccountLocked(opUser.getAccountLocked().booleanValue() ? SpringUtils
				.getI18nMessage("webapp.constant.yes") : SpringUtils
				.getI18nMessage("webapp.constant.no"));
		row.setCredentialsExpired(opUser.getCredentialsExpired().booleanValue() ? SpringUtils
				.getI18nMessage("webapp.constant.yes") : SpringUtils
				.getI18nMessage("webapp.constant.no"));
		row.setCreateTime(DateUtils.formatAsString(opUser.getCreateTime()));
		row.setUpdateTime(DateUtils.formatAsString(opUser.getUpdateTime()));
		Set<Role> roleList = opUser.getRoles();
		if (roleList != null) {
			StringBuilder roles = new StringBuilder();
			List<Long> roleIds = new ArrayList<Long>();
			for (Role role : roleList) {
				if (roles.length() != 0) {
					roles.append("，");
				}
				roles.append(role.getDisplayName()).append("(")
						.append(role.getName()).append(")");
				roleIds.add(role.getId());
			}
			row.setRoleIds(roleIds);
			row.setRoles(roles.toString());
		}
		return row;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.general.op.manager.OpUserManager#addOpUser(com.general.op.model.vo
	 * .AddOpUserForm)
	 */
	@Override
	public OpUserRow addOpUser(AddOpUserForm addOpUserForm)
			throws ServiceException {
		if (addOpUserForm == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.addOpUser.FormNotNull"));
		}
		// 检查用户名是否存在
		if (isUsernameExist(addOpUserForm.getUsername(), null)) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.addOpUser.IsNameExist"));
		}
		// 检查用户Email是否存在
		if (isEmailExist(addOpUserForm.getEmail(), null)) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.addOpUser.IsEmailExist"));
		}
		// 检查角色是否存在
		List<Long> roleIds = addOpUserForm.getRoleIds();
		if (!isRolesAllExist(roleIds)) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.addOpUser.AreRolesExist"));
		}
		OpUser opUser = createNewOpUser(addOpUserForm);
		Long addId = opUserMapper.insert(opUser);
		if(addId != null) {
			// 删除角色信息以重新授权
			roleMapper.deleteUserRoleByUserId(addId);
			// 授权角色
			if (roleIds != null && !roleIds.isEmpty()) {
				UserRole userRole;
				for (Long roleId : roleIds) {
					userRole = new UserRole();
					userRole.setUserId(addId);
					userRole.setRoleId(roleId);
					roleMapper.saveUserRole(userRole);
				}
			}
		}
		opUser = getOpUserWithRoles(addId);
		return createOpUserRow(opUser);
	}

	/**
	 * 检查用户Email是否已存在.
	 * 
	 * @param email
	 * @param oldId
	 * @return
	 */
	protected boolean isEmailExist(String email, Long oldId) {
		OpUser opUser = opUserMapper.getByEmail(email);
		if (opUser != null) {
			if (oldId != null) {
				return !oldId.equals(opUser.getId());
			}
			return true;
		}
		return false;
	}

	/**
	 * 检查用户名是否已存在.
	 * 
	 * @param username
	 * @param oldId
	 * @return
	 */
	protected boolean isUsernameExist(String username, Long oldId) {
		OpUser opUser = opUserMapper.getByUsername(username);
		if (opUser != null) {
			if (oldId != null) {
				return !oldId.equals(opUser.getId());
			}
			return true;
		}
		return false;
	}

	/**
	 * 检查角色是否都存在.
	 * 
	 * @param roleIds
	 * @return
	 */
	protected boolean isRolesAllExist(List<Long> roleIds) {
		if (roleIds != null && !roleIds.isEmpty()) {
			for (Long roleId : roleIds) {
				if (roleMapper.get(roleId) == null) {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * 创建新用户. 密码使用加密.
	 * 
	 * @param addOpUserForm
	 * @return
	 */
	protected OpUser createNewOpUser(AddOpUserForm addOpUserForm) {
		OpUser newOpUser = new OpUser();

		newOpUser.setUsername(addOpUserForm.getUsername());
		newOpUser.setPassword(EncryptUtils.saltSHA256(defaultCredentialsSalt,
				addOpUserForm.getUsername() + DEFAULT_NEW_PASSWORD));
		newOpUser.setEmail(addOpUserForm.getEmail());
		newOpUser.setRealName(addOpUserForm.getRealName());
		newOpUser.setTel(addOpUserForm.getTel());
		newOpUser
				.setAccountDisabled(addOpUserForm.getAccountDisabled().equals(
						SpringUtils.getI18nMessage("webapp.constant.yes")) ? Boolean.TRUE
						: Boolean.FALSE);
		newOpUser
				.setAccountExpired(addOpUserForm.getAccountExpired().equals(
						SpringUtils.getI18nMessage("webapp.constant.yes")) ? Boolean.TRUE
						: Boolean.FALSE);
		newOpUser
				.setAccountLocked(addOpUserForm.getAccountLocked().equals(
						SpringUtils.getI18nMessage("webapp.constant.yes")) ? Boolean.TRUE
						: Boolean.FALSE);
		newOpUser
				.setCredentialsExpired(addOpUserForm.getCredentialsExpired()
						.equals(SpringUtils
								.getI18nMessage("webapp.constant.yes")) ? Boolean.TRUE
						: Boolean.FALSE);
		return newOpUser;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.general.op.manager.OpUserManager#updateOpUser(com.general.op.model
	 * .vo.UpdateOpUserForm)
	 */
	@Override
	public OpUserRow updateOpUser(UpdateOpUserForm updateOpUserForm)
			throws ServiceException {
		if (updateOpUserForm == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updateOpUser.FormNotNull"));
		}
		if (updateOpUserForm.getId() == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updateOpUser.IdNotNull"));
		}
		OpUser opUser = opUserMapper.get(updateOpUserForm.getId());
		// 检查用户是否存在
		if (opUser == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updateOpUser.NotExist"));
		}
		// 检查用户名是否存在
		if (isUsernameExist(updateOpUserForm.getUsername(),
				updateOpUserForm.getId())) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updateOpUser.IsNameExist"));
		}
		// 检查用户Email是否存在
		if (isEmailExist(updateOpUserForm.getEmail(), updateOpUserForm.getId())) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updateOpUser.IsEmailExist"));
		}
		// 检查角色是否存在
		List<Long> roleIds = updateOpUserForm.getRoleIds();
		if (!isRolesAllExist(roleIds)) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updateOpUser.AreRolesExist"));
		}
		opUser = createUpdateOpUser(updateOpUserForm);
		Integer ret = opUserMapper.update(opUser);
		if(ret != null && ret == 1){
			// 删除角色信息以重新授权
			roleMapper.deleteUserRoleByUserId(opUser.getId());
			// 授权角色
			if (roleIds != null && !roleIds.isEmpty()) {
				UserRole userRole;
				for (Long roleId : roleIds) {
					userRole = new UserRole();
					userRole.setUserId(opUser.getId());
					userRole.setRoleId(roleId);
					roleMapper.saveUserRole(userRole);
				}
			}
		}
		opUser = getOpUserWithRoles(opUser.getId());
		return createOpUserRow(opUser);
	}

	/**
	 * 修改用户.
	 * 
	 * @param updateOpUserForm
	 * @return
	 */
	protected OpUser createUpdateOpUser(UpdateOpUserForm updateOpUserForm) {
		OpUser updateOpUser = new OpUser();

		updateOpUser.setId(updateOpUserForm.getId());
		updateOpUser.setUsername(updateOpUserForm.getUsername());
		updateOpUser.setEmail(updateOpUserForm.getEmail());
		updateOpUser.setRealName(updateOpUserForm.getRealName());
		updateOpUser.setTel(updateOpUserForm.getTel());
		updateOpUser
				.setAccountDisabled(updateOpUserForm.getAccountDisabled()
						.equals(SpringUtils
								.getI18nMessage("webapp.constant.yes")) ? Boolean.TRUE
						: Boolean.FALSE);
		updateOpUser
				.setAccountExpired(updateOpUserForm.getAccountExpired().equals(
						SpringUtils.getI18nMessage("webapp.constant.yes")) ? Boolean.TRUE
						: Boolean.FALSE);
		updateOpUser
				.setAccountLocked(updateOpUserForm.getAccountLocked().equals(
						SpringUtils.getI18nMessage("webapp.constant.yes")) ? Boolean.TRUE
						: Boolean.FALSE);
		updateOpUser
				.setCredentialsExpired(updateOpUserForm.getCredentialsExpired()
						.equals(SpringUtils
								.getI18nMessage("webapp.constant.yes")) ? Boolean.TRUE
						: Boolean.FALSE);

		return updateOpUser;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.general.op.manager.OpUserManager#getOpUserWithRoles(java.lang.Long)
	 */
	@Override
	public OpUser getOpUserWithRoles(Long opUserId) throws ServiceException {
		OpUser opUser = opUserMapper.get(opUserId);
		if (opUser != null) {
			List<Role> roleList = roleMapper.getByUserId(opUser.getId());
			if (roleList != null) {
				opUser.setRoles(new LinkedHashSet<Role>(roleList));
			}
		}
		return opUser;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.general.op.manager.OpUserManager#updateAccount(com.general.op.model
	 * .vo.UpdateAccountForm)
	 */
	@Override
	public OpUser updateAccount(UpdateAccountForm updateAccountForm)
			throws ServiceException {

		if (updateAccountForm == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updateAccount.FormNotNull"));
		}
		OpUser opUser = opUserMapper.getByUsername(ShiroUtils.getPrincipal());
		// 检查用户是否存在
		if (opUser == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updateAccount.NotExist"));
		}
		// 检查用户Email是否存在
		if (isEmailExist(updateAccountForm.getEmail(), opUser.getId())) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updateAccount.IsEmailExist"));
		}
		opUser = createUpdateOpUser(updateAccountForm, opUser.getId());
		Integer ret = opUserMapper.update(opUser);
		opUser = opUserMapper.get(opUser.getId());
		return opUser;
	}

	/**
	 * 修改部分用户信息.
	 * 
	 * @param updateAccountForm
	 * @return
	 */
	protected OpUser createUpdateOpUser(UpdateAccountForm updateAccountForm,
			Long id) {
		OpUser updateOpUser = new OpUser();
		updateOpUser.setId(id);
		updateOpUser.setEmail(updateAccountForm.getEmail());
		updateOpUser.setRealName(updateAccountForm.getRealName());
		updateOpUser.setTel(updateAccountForm.getTel());

		return updateOpUser;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.general.op.manager.OpUserManager#getWithRolesByUsername(java.lang
	 * .String)
	 */
	@Override
	public OpUserRow getWithRolesByUsername(String username)
			throws ServiceException {
		OpUser user = opUserMapper.getByUsername(username);
		user = getOpUserWithRoles(user.getId());
		return createOpUserRow(user);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.general.op.manager.OpUserManager#updatePassword(com.general.op.model
	 * .vo.UpdatePasswordForm)
	 */
	@Override
	public boolean updatePassword(UpdatePasswordForm updatePasswordForm)
			throws ServiceException {

		if (updatePasswordForm == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updatePassword.FormNotNull"));
		}
		// 检查重复新密码是否一致
		if (!updatePasswordForm.getNewPassword().equals(
				updatePasswordForm.getRePassword())) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updatePassword.WrongRePassword"));
		}
		String username = ShiroUtils.getPrincipal();
		OpUser opUser = opUserMapper.getByUsername(username);
		// 检查用户是否存在
		if (opUser == null) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updatePassword.NotExist"));
		}
		// 检查原密码是否正确
		if (!isPasswordRight(username, updatePasswordForm.getPassword())) {
			throw new ServiceException(
					SpringUtils
							.getI18nMessage("webapp.service.OpUserManagerImpl.updatePassword.WrongPassword"));
		}
		opUser = createUpdateOpUser(updatePasswordForm, opUser.getId());
		Integer ret = opUserMapper.update(opUser);
		return (ret == null || ret != 1) ? false : true;
	}

	/**
	 * 修改用户密码.
	 * 
	 * @param updatePasswordForm
	 * @param id
	 * @return
	 */
	protected OpUser createUpdateOpUser(UpdatePasswordForm updatePasswordForm,
			Long id) {
		OpUser updateOpUser = new OpUser();
		updateOpUser.setId(id);
		updateOpUser.setPassword(EncryptUtils.saltSHA256(
				defaultCredentialsSalt, updatePasswordForm.getNewPassword()));

		return updateOpUser;
	}

	/**
	 * 检查密码是否正确.
	 * 
	 * @param username
	 * @param password
	 * @return
	 */
	protected boolean isPasswordRight(String username, String password) {
		OpUser user = opUserMapper.getByUsername(username);
		String encryptedPwd = EncryptUtils.saltSHA256(defaultCredentialsSalt,
				password);
		return encryptedPwd.equals(user.getPassword());
	}

}
